Using VR Input
Using the VR Sample Script with XR Interaction Toolkit
To use Easy Dimension Measurement System in VR, you can download the VR Sample Script from the package manager to see how to set up the system for VR. This script is fully compatible with XR Interaction Toolkit 2.2.0. Since there are various VR integration packages, we won't include the VR scene inside the package to avoid any conflict and messy errors in your scene. Instead, we will look at the main logic of using Easy Dimension inside your VR scene.
To get started, go back to the Quick Start section and look at the inspector when StarterGO is selected. You will see that the first field is Draw In Vr Comp. To use Easy Dimension in VR, you need to add the DrawInVR.cs component to the StarterGO and drag and drop the StarterGO inside the Draw In Vr Comp section.
Comparing Mouse Input and VR Input in Easy Dimension Measurement System
In Easy Dimension, there are some differences between using mouse input and VR input. When using mouse input, a draw step occurs for every dimension, and each step passes after a mouse click. The Camera.ScreenPointToRay(Mouse.current.position.ReadValue())
method is used to catch the raycastHit
. However, when using VR input, this approach is not possible as we cannot use screen coordinates or mouse clicks to pass draw steps. Instead, we should use bool ray = rayInteractor.TryGetCurrent3DRaycastHit(out hit)
to catch the hit, and we need to have a boolean that turns true after a desired button is pressed. To achieve this, we need to get one of our ray interactors from one hand and feed it to the DrawInVR.rayInteractor
. For more information, please see the Scripting Manual section.
DrawInVR.cs works dependently with EzDimStarter component. They should both be added to the same GameObject, which we have called StarterGO. You need to drag and drop StarterGO inside the Draw In Vr Comp field.
Practical Example
To ensure that you understand how to use the DrawInVR.cs component, let's look at an example. You can download the DrawInVR.cs sample from the package manager and open it. In this sample, you will find some public void functions that are similar to the ones we saw in the EzDimStarter component.
public void VR_EzPointToPointDimension(EzDimStarter _starterScript)
{
if (!_starterScript.isCreating)
{
firstStep = true;
secoundStep = thirdStep = fourthStep = fifthStep = sixthStep = false;
_starterScript.isCreating = true; // this bool will set to false after draw the dimension.
_starterScript.SelectionList.Clear();
Funcs.UpdateAll(_starterScript, _starterScript.DimensionsList, _starterScript.SelectionList);
GameObject EzPointToPointDimensionGO = new GameObject("VR_EzPointToPointDimension");
EzPointToPointDimensionGO.transform.parent = _starterScript.transform;
var p2PDim = EzPointToPointDimensionGO.AddComponent<PointToPointDimension>();
if (_starterScript.createDimensionCort != null)
StopCoroutine(_starterScript.createDimensionCort);
_starterScript.createDimensionCort = StartCoroutine(CreatePointToPointDimension(_starterScript, p2PDim));
_starterScript.DimensionsList.Add(EzPointToPointDimensionGO.gameObject); // add the parent GO to the list.
}
}
It's quite similar to the previous example we discussed. Note that we didn't have a separate dimension list and we still send some data to the EzDimStarter script.
The creation process happens inside the IEnumerator CreatePointToPointDimension()
function, which is quite similar to what we did before when using mouse input.
IEnumerator CreatePointToPointDimension(EzDimStarter _starterScript, PointToPointDimension _p2PDim)
{
_p2PDim.secondDrawStep = false;
while (_p2PDim.isDone != true)
{
if (firstStep && secoundStep && !thirdStep && !_p2PDim.secondDrawStep && _starterScript.isCreating)
{
RaycastHit hit;
bool ray = rayInteractor.TryGetCurrent3DRaycastHit(out hit);
if (ray)
{
_p2PDim.pointA = hit.point;
_p2PDim.objectA = hit.transform.gameObject;
_p2PDim.objectATransformGO.transform.position = hit.transform.position;
_p2PDim.objectATransformGO.transform.rotation = hit.transform.rotation;
_p2PDim.objectATransformGO.transform.localScale = hit.transform.localScale;
_p2PDim.pointATransformGO.transform.position = _p2PDim.pointA;
if (!hit.transform.gameObject.TryGetComponent<EzDynamicTargetObject>(out EzDynamicTargetObject EzDynamicTarget))
{
hit.transform.gameObject.AddComponent<EzDynamicTargetObject>().p2PDimComponentsList.Add(_p2PDim);
hit.transform.gameObject.GetComponent<EzDynamicTargetObject>().starterScript = _starterScript;
}
else
{
var p2PDimComp = hit.transform.gameObject.GetComponent<EzDynamicTargetObject>();
p2PDimComp.p2PDimComponentsList.Add(_p2PDim);
}
_p2PDim.secondDrawStep = true;
}
}
else if (_p2PDim.secondDrawStep == true)
{
Funcs.SetActiveAllChilds(_p2PDim.gameObject.transform, true);
RaycastHit hit;
bool ray = rayInteractor.TryGetCurrent3DRaycastHit(out hit);
if (ray)
{
_p2PDim.pointB = hit.point;
_p2PDim.objectB = hit.transform.gameObject;
_p2PDim.objectBTransformGO.transform.position = hit.transform.position;
_p2PDim.objectBTransformGO.transform.rotation = hit.transform.rotation;
_p2PDim.objectBTransformGO.transform.localScale = hit.transform.localScale;
_p2PDim.pointBTransformGO.transform.position = _p2PDim.pointB;
_p2PDim.UpdateDimension(_p2PDim.pointA, _p2PDim.pointB, _p2PDim.lineThickness, _p2PDim.textSize, _p2PDim.textOffset,
_p2PDim.numberColor, _p2PDim.mainColor, _p2PDim.arrowColor,
_p2PDim.mainLineMat, _p2PDim.arrowMat, _p2PDim.cameraTransform, _p2PDim.mainParent, _p2PDim.arrowHeight,
InternalFunctions.LengthUnitCalculator(_starterScript), _p2PDim.textTowardsCameraOffset, _p2PDim.NormalOffset);
if (firstStep && secoundStep && thirdStep)
{
if (!hit.transform.gameObject.TryGetComponent<EzDynamicTargetObject>(out EzDynamicTargetObject EzDynamicTarget))
{
hit.transform.gameObject.AddComponent<EzDynamicTargetObject>().p2PDimComponentsList.Add(_p2PDim);
hit.transform.gameObject.GetComponent<EzDynamicTargetObject>().starterScript = _starterScript;
}
else
{
var p2PDimComp = hit.transform.gameObject.GetComponent<EzDynamicTargetObject>();
p2PDimComp.p2PDimComponentsList.Add(_p2PDim);
}
_starterScript.isCreating = false; // end of drawing of the dimension.
_p2PDim.secondDrawStep = false;
_p2PDim.isDone = true;
}
}
}
yield return null;
}
}
The only differences are the condition of going to the next step and how we get the raycastHit
. Other steps are almost similar to what we did with mouse input.